package javaNIO1.channel;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.Random;

/**
 * Created with Intel IDEA.
 * <p>
 * 文件锁
 *
 * @Auther: gjt
 * @Date: 2024/7/14 13:49
 */
public class fileLock {

    private static final int SIZE_INT = 4;
    private static final int INDEX_START = 0;
    private static final int INDEX_COUNT = 10;
    private static final int INDEX_SIZE = INDEX_COUNT * SIZE_INT;
    private ByteBuffer buffer = ByteBuffer.allocate(INDEX_SIZE);

    // 字节缓冲区可以转成 in shot long double float
    private IntBuffer indexBuffer = buffer.asIntBuffer();

    private Random rand = new Random();

    public static void main(String[] args) throws IOException, InterruptedException {
        boolean write = false;
        String path = " ";
        if (args.length != 2) {
            System.out.println("请使用可以读写的文件！");
            return;
        }

        write = args[0].equals("-w");

        path = args[1];
        RandomAccessFile file = new RandomAccessFile(path, (write) ? "rw" : "r");
        // 获取文件通道
        FileChannel channel = file.getChannel();

        fileLock fileLock = new fileLock();
        if (write) {
            fileLock.doUpdates(channel);
        } else {
            fileLock.doQueries(channel);
        }
    }

    void doQueries(FileChannel fc) throws IOException, InterruptedException {
        while (true) {
            System.out.println("尝试加分享锁");
            // 枷锁
            FileLock lock = fc.lock(INDEX_START, INDEX_SIZE, true);

            try{
                int reps = rand.nextInt(60) + 20;

                for (int i = 0; i < reps; i++) {
                    int n = rand.nextInt(INDEX_COUNT);

                    int position = INDEX_START + (n * INDEX_SIZE);

                    buffer.clear();
                    fc.read(buffer, position);

                    int value = indexBuffer.get(n);
                    System.out.println("键；" + n + ",值：" + value);
                    Thread.sleep(100);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.release();
            }
            System.out.println("seeping");
            Thread.sleep(rand.nextInt(3000) + 5000);
        }
    }

    void doUpdates(FileChannel fc) throws IOException, InterruptedException {
        while(true){
            System.out.println("加独占锁");
            FileLock lock = fc.lock(INDEX_START, INDEX_SIZE, false);
            try{
                updateIndex(fc);
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                lock.release();
            };
            System.out.println("seeping");
            Thread.sleep(rand.nextInt(200) + 500);
        }
    }


    private int idxval = 1;

    private void updateIndex(FileChannel fc) throws InterruptedException, IOException {
        indexBuffer.clear();
        for (int i = 0; i < INDEX_COUNT; i++) {
            idxval++;
            System.out.println("键：" + i + ",值：" + idxval);
            indexBuffer.put(idxval);
            Thread.sleep(500);
        }

        buffer.clear();
        fc.write(buffer,INDEX_START);
    }
}
